﻿//-----------------------------------------------------------------------
//  This file is part of the Microsoft Code Samples.
// 
//  Copyright (C) Microsoft Corporation.  All rights reserved.
// 
//  This source code is intended only as a supplement to Microsoft
//  Development Tools and/or on-line documentation.  See these other
//  materials for detailed information regarding Microsoft code samples.
// 
//  THIS CODE AND INFORMATION ARE PROVIDED AS IS WITHOUT WARRANTY OF ANY
//  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
//  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
//  PARTICULAR PURPOSE.
//-----------------------------------------------------------------------

#region Using directives

using System;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Windows.Forms;
using System.Data.SqlClient;
using System.Configuration;
using System.Management;
using System.Timers;
using System.Globalization;
using Microsoft.SqlServer;
using Microsoft.SqlServer.MessageBox;
using Microsoft.SqlServer.Replication;

using System.Diagnostics;

#endregion

namespace Microsoft.Samples.SqlServer
{
    partial class SalesOrders : Form
    {
        private SqlConnection localConn;

        private enum ConnectedState
        {
            Connected,
            Disconnected
        }

        public SalesOrders()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Load the main form and fill the dataset with data from the AdventureWorks database.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void SalesOrders_Load(object sender, EventArgs e)
        {
            try
            {
                this.Show();

				// Disable the Synchronize When Connectioned menu item on Win2K computers.
				if (Environment.OSVersion.Version.Minor < 1)
				{
					mnuSyncWhenConnected.Enabled = false;
				}

                Synchronize syncSub = new Synchronize();

                // Disable the current form
                this.Enabled = false;

                syncSub.Show(this);

                // Check that the subscription exists.
                syncSub.CheckSubscription();

				// Disable upload only if Web synchronization is enabled.
				if (syncSub.UseWebSynchronization)
				{
					mnuSynchronizeOnlyUploadData.Enabled = false;
				}
				
                // Reload data from database
                FillDataSet();
            }
            catch (SqlException ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(
                    Properties.Resources.ExceptionVerifySqlServerRunning,
                    Properties.Resources.ExceptionSqlServerError,
                    ExceptionMessageBoxButtons.OK);
                emb.InnerException = ex;
                emb.Show(this);

                // Shutdown the application because we can't continue.
                Application.Exit();
            }
            catch (ApplicationException ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(ex,
                    ExceptionMessageBoxButtons.OK);
                emb.Show(this);

                // Shutdown the application because we can't continue.
                Application.Exit();
            }
            catch (Exception ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(ex,
                    ExceptionMessageBoxButtons.OK);
                emb.Show(this);

                emb = new ExceptionMessageBox(Properties.Resources.CatastrophicFailure,
                    Properties.Resources.ClosingApplication);
                emb.Show(this);

                // Shutdown the application because we can't continue.
                Application.Exit();
            }
            finally
            {
                // Enable the current form
                this.Enabled = true;
            }
        }

        /// <summary>
        /// Fill the dataset with data from the AdventureWorksLocal database.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2201:DoNotRaiseReservedExceptionTypes")]
        private void FillDataSet()
        {
            // Build the local connection string.

            SqlConnectionStringBuilder sb = new SqlConnectionStringBuilder();
            sb.IntegratedSecurity = true;
            sb.DataSource = (Properties.Settings.Default.Publisher == "localhost"
                    ? Environment.MachineName : Properties.Settings.Default.Subscriber);
            sb.InitialCatalog = Properties.Settings.Default.SubscriptionDatabase;

            localConn = new SqlConnection(sb.ToString());

            try
            {
                localConn.Open();

                // Empty the dataset
                this.adventureWorksLocalDataSet.Clear();

                // Load Status text values
                this.ufnGetStatusTextTableTableAdapter.Connection = localConn;
                this.ufnGetStatusTextTableTableAdapter.Fill(
                    this.adventureWorksLocalDataSet.ufnGetStatusTextTable);

                // Load Customers
                this.uspStoreSelectCommandTableAdapter.Connection = localConn;
                this.uspStoreSelectCommandTableAdapter.Fill(
                    this.adventureWorksLocalDataSet.uspStoreSelectCommand);

                // Load Sales Order Headers
                this.uspSalesOrderHeaderSelectCommandTableAdapter.Connection = localConn;
                this.uspSalesOrderHeaderSelectCommandTableAdapter.Fill(
                    this.adventureWorksLocalDataSet.uspSalesOrderHeaderSelectCommand);

                // Load Sales Order Details
                this.uspSalesOrderDetailSelectCommandTableAdapter.Connection = localConn;
                this.uspSalesOrderDetailSelectCommandTableAdapter.Fill(
                    this.adventureWorksLocalDataSet.uspSalesOrderDetailSelectCommand);

                this.uspStoreSelectCommandBindingSource.PositionChanged
                    += new EventHandler(CustomerPosition_Changed);
            }
            catch (Exception ex)
            {
                throw new ApplicationException(
                    Properties.Resources.ExceptionCannotConnectLocal, ex);
            }
            finally
            {
                localConn.Close();
            }
        }

        private void CustomerPosition_Changed(object sender, EventArgs e)
        {
            UpdateControls();
        }

        /// <summary>
        /// Exit the application.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuFileExit_Click(object sender, EventArgs e)
        {
            this.Close();
            //Application.Exit();
        }

        /// <summary>
        /// Create a new sales order.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuOrderNew_Click(object sender, EventArgs e)
        {
            CreateNewOrder();

            UpdateControls();
        }

        /// <summary>
        /// Edit the currently selected sales order.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void mnuOrderEdit_Click(object sender, EventArgs e)
        {
            EditCurrentOrder();

            UpdateControls();
        }

        /// <summary>
        /// Create a new sales order.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void NewOrderButton_Click(object sender, EventArgs e)
        {
            CreateNewOrder();

            UpdateControls();
        }

        /// <summary>
        /// Edit the currently selected sales order.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void EditOrderButton_Click(object sender, EventArgs e)
        {
            EditCurrentOrder();

            UpdateControls();
        }

        /// <summary>
        /// Synchronize all the data in the database.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void mnuSynchronizeAllData_Click(object sender, EventArgs e)
        {
            try
            {
                Synchronize syncSub = new Synchronize();

                // Disable the current form
                this.Enabled = false;

                syncSub.Show(this);

                syncSub.SynchronizeSubscriptionFull();

                // Reload data from database
                FillDataSet();

                UpdateControls();
            }
            catch (Exception ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(ex,
                    ExceptionMessageBoxButtons.OK);
                emb.Show(this);
            }
            finally
            {
                // Enable the current form
                this.Enabled = true;
            }
        }

        /// <summary>
        /// Synchronize only the data in the database that has changed.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void mnuSynchronizeOnlyUploadData_Click(object sender, EventArgs e)
        {
            try
            {
                Synchronize syncSub = new Synchronize();

                // Disable the current form
                this.Enabled = false;

                syncSub.Show(this);

                syncSub.SynchronizeSubscriptionUploadOnly();

                // Reload data from database
                FillDataSet();

                UpdateControls();
            }
            catch (Exception ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(ex,
                    ExceptionMessageBoxButtons.OK);
                emb.Show(this);
            }
            finally
            {
                // Enable the current form
                this.Enabled = true;
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void mnuSynchronizeAdvancedUploadAndReinitializeData_Click(object sender, EventArgs e)
        {
            try
            {
                Synchronize syncSub = new Synchronize();

                // Disable the current form
                this.Enabled = false;

                syncSub.Show(this);

                syncSub.ReinitializeSubscriptionWithUpload();

                // Reload data from database
                FillDataSet();

                UpdateControls();
            }
            catch (Exception ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(ex,
                    ExceptionMessageBoxButtons.OK);
                emb.Show(this);
            }
            finally
            {
                // Enable the current form
                this.Enabled = true;
            }
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void mnuSynchronizeAdvancedReinitializeData_Click(object sender, EventArgs e)
        {
            try
            {
                Synchronize syncSub = new Synchronize();

                // Disable the current form
                this.Enabled = false;

                syncSub.Show(this);

                syncSub.ReinitializeSubscription();

                // Reload data from database
                FillDataSet();

                UpdateControls();
            }
            catch (Exception ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(ex,
                    ExceptionMessageBoxButtons.OK);
                emb.Show(this);
            }
            finally
            {
                // Enable the current form
                this.Enabled = true;
            }
        }

        /// <summary>
        /// Open the edit form to edit the currently selected sales order passing the current dataset and binding context to position the record pointer.
        /// </summary>
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void EditCurrentOrder()
        {
            EditOrder editOrder;

            try
            {
                editOrder = new EditOrder(this.adventureWorksLocalDataSet,
                    this.uspSalesOrderHeaderSelectCommandBindingSource,
                    this.ufnGetStatusTextTableBindingSource, false);
                editOrder.ShowDialog(this);

                if (this.adventureWorksLocalDataSet.HasChanges())
                {
                    // Update database
                    this.uspSalesOrderHeaderSelectCommandTableAdapter.Update(
                        this.adventureWorksLocalDataSet.uspSalesOrderHeaderSelectCommand);
                    this.uspSalesOrderDetailSelectCommandTableAdapter.Update(
                        this.adventureWorksLocalDataSet.uspSalesOrderDetailSelectCommand);
                }
            }
            catch (SqlException ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(ex,
                    ExceptionMessageBoxButtons.OK);
                emb.Show(this);
            }
            catch (Exception ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(ex,
                    ExceptionMessageBoxButtons.OK);
                emb.Show(this);

                // Shutdown the application because we can't continue.
                Application.Exit();
            }
        }

        /// <summary>
        /// Open the edit form to create a new sales order passing the current 
        /// dataset and binding context to position the record pointer.
        /// </summary>
        private void CreateNewOrder()
        {
            EditOrder editOrder;

            try
            {
                editOrder = new EditOrder(this.adventureWorksLocalDataSet,
                    this.uspSalesOrderHeaderSelectCommandBindingSource,
                        this.ufnGetStatusTextTableBindingSource, true);
                editOrder.ShowDialog(this);

                if (this.adventureWorksLocalDataSet.HasChanges())
                {
                    // Update database
                    this.uspSalesOrderHeaderSelectCommandTableAdapter.Update(
                        this.adventureWorksLocalDataSet.uspSalesOrderHeaderSelectCommand);
                    this.uspSalesOrderDetailSelectCommandTableAdapter.Update(
                        this.adventureWorksLocalDataSet.uspSalesOrderDetailSelectCommand);
                    this.adventureWorksLocalDataSet.AcceptChanges();

                    // Position combobox to new record
                    SalesOrderComboBox.SelectedIndex = SalesOrderComboBox.Items.Count - 1;
                }
            }
            catch (SqlException ex)
            {
                this.adventureWorksLocalDataSet.RejectChanges();

                ExceptionMessageBox emb = new ExceptionMessageBox(ex,
                    ExceptionMessageBoxButtons.OK);
                emb.Show(this);
            }
        }

        /// <summary>
        /// Enable or disable the controls based on whether there is a 
        /// current sales order selected.
        /// </summary>
        private void UpdateControls()
        {
            if (this.uspSalesOrderHeaderSelectCommandBindingSource.Position >= 0)
            {
                SalesOrderComboBox.Enabled = true;
                EditOrderButton.Enabled = true;
            }
            else
            {
                SalesOrderComboBox.Enabled = false;
                EditOrderButton.Enabled = false;
            }
        }

        private void mnuWebSync_Click(object sender, EventArgs e)
        {
            WebSyncOptions subscriptionWebSync = new WebSyncOptions();
            DialogResult dr = subscriptionWebSync.ShowDialog(this);

			if (dr == DialogResult.OK)
			{
				// If Web synchronization is enabled, disable upload only options.
				if (subscriptionWebSync.WebSynchronizationEnabled)
				{
					mnuSynchronizeOnlyUploadData.Enabled = false;
				}
				else
				{
					mnuSynchronizeOnlyUploadData.Enabled = true;
				}
			}

            UpdateControls();
        }

        private void mnuSyncWhenConnected_Click(object sender, EventArgs e)
        {
            // Toggle the menu check box.
            if (mnuSyncWhenConnected.Checked)
            {
                mnuSyncWhenConnected.Checked = false;
                syncTimer.Enabled = false;
                syncWhenConnectedStrip.Visible = false;
                syncWhenConnectedText.Text = string.Empty;
            }
            else
            {
                mnuSyncWhenConnected.Checked = true;
                syncTimer.Enabled = true;
                syncTimer.Interval = 1000 * Convert.ToDouble(
                    Properties.Settings.Default.SyncWhenConnectedInterval,
                    CultureInfo.InvariantCulture);
                syncWhenConnectedStrip.Visible = true;

                // Raise timer event immediately.
                syncTimer_Elapsed(null, null);

            }

            UpdateControls();
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private void syncTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            Synchronize syncSub;

            // Start a background synchronization if an Internet connection is
            // available and data is not being edited.
            if (GetConnectionState() == ConnectedState.Connected)
            {
                syncWhenConnectedIcon.Image = Properties.Resources.connected;

                if (this.ContainsFocus == true)
                {
                    // Instantiate the replication code without the Form.
                    syncSub = new Synchronize();


                    syncWhenConnectedText.Text
                       = Properties.Resources.StatusSyncStarting;

                    syncWhenConnectedIcon.Image = Properties.Resources.synchronizing;

                    try
                    {
                        syncSub.Status += new SyncWhenConnectedStatus(syncSub_Status);
                        syncSub.SynchronizeSubscriptionFull();

                        syncWhenConnectedText.Text
                            = Properties.Resources.StatusSyncComplete;
                    }
                    catch
                    {
                        syncWhenConnectedText.Text
                            = Properties.Resources.StatusSyncFailed;
                    }
                    finally
                    {
                        syncWhenConnectedIcon.Image = Properties.Resources.connected;

                        // Reload data from database
                        FillDataSet();

                        UpdateControls();
                    }
                }
            }
            else
            {
                syncWhenConnectedIcon.Image = Properties.Resources.disconnected;
            }
        }

        void syncSub_Status(object sender, StatusEventArgs e)
        {
            // Update the Synchronization Status form.
            syncWhenConnectedStatus.Value = (int)e.PercentCompleted;

            switch (e.MessageStatus)
            {
                case MessageStatus.Start:
                    syncWhenConnectedText.Text = Properties.Resources.StatusSyncStarting;
                    break;
                case MessageStatus.InProgress:
                    syncWhenConnectedText.Text = Properties.Resources.StatusSyncInProgress;
                    break;
                case MessageStatus.Succeed:
                    syncWhenConnectedText.Text = Properties.Resources.StatusSyncComplete;
                    break;
                case MessageStatus.Fail:
                    syncWhenConnectedText.Text = Properties.Resources.StatusSyncFailed;
                    break;
                default:
                    syncWhenConnectedText.Text = Properties.Resources.StatusSyncComplete;
                    break;
            }
            Application.DoEvents();
        }

        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
        private ConnectedState GetConnectionState()
        {
            SelectQuery wmiQuery;
            ManagementObjectSearcher searcher;
            bool isConnected;

            try
            {
                // Query the WMI provider to determine if we are connected.
                wmiQuery = new SelectQuery("SELECT * FROM Win32_NetworkAdapter");
                searcher = new ManagementObjectSearcher(wmiQuery);

                // Assume that we are not connected.
                isConnected = false;

                // Check the results for a NetConnectionStatus of 2 (connected).
                foreach (ManagementObject result in searcher.Get())
                {
                    if (Convert.ToInt32(result["NetConnectionStatus"],
                        System.Globalization.CultureInfo.InvariantCulture) == 2)
                    {
                        isConnected = true;
                    }
                }

                if (isConnected)
                {
                    return ConnectedState.Connected;
                }
                else
                {
                    return ConnectedState.Disconnected;
                }
            }
            catch (Exception ex)
            {
                ExceptionMessageBox emb = new ExceptionMessageBox(ex);
                emb.Show(this);
                return ConnectedState.Disconnected;
            }
        }

        private void mnuSubscriptionStatus_Click(object sender, EventArgs e)
        {
            SubscriberMonitor subMonitor = new SubscriberMonitor(
                Properties.Settings.Default.Subscriber,
                Properties.Settings.Default.Publication,
                (Properties.Settings.Default.Publisher == "localhost"
                    ? Environment.MachineName : Properties.Settings.Default.Publisher),
                Properties.Settings.Default.PublicationDatabase,
                Properties.Settings.Default.SubscriptionDatabase);
            subMonitor.Show(this);
            Application.DoEvents();
        }

        private void mnuAbout_Click(object sender, EventArgs e)
        {
            AboutBoxSalesOrders dlgAbout;

            dlgAbout = new AboutBoxSalesOrders();
            dlgAbout.ShowDialog();
            dlgAbout.Dispose();
        }

        private void syncWhenConnectedText_Click(object sender, EventArgs e)
        {
            mnuSubscriptionStatus_Click(null, null);
        }

        private void salesOrderDetailDataGridView_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            EditCurrentOrder();
        }
    }
}
